<?php
class Facebook {
	
	public $appId, $appSerect, $email, $password, $returnUrl;
	
	public $limit = 10;

	protected $_accessToken = null;
	
	protected $_tokenFile;

	public function init($configs=array()) {
		$this->_tokenFile = Yii::app()->basePath . DIRECTORY_SEPARATOR . 'token.txt';
		foreach($configs as $name => $value) {
			$this->$name = $value;
		}
	}

	public function getAccessToken() {
		if (!$this->_accessToken) {
			$token = $this->_getLocalAccessToken();
			if (!$token) {
				$token = $this->_getAccessTokenByLogin();
			}
			$this->_accessToken = $token;
		}
		return $this->_accessToken;
	}
	
	protected function _getLocalAccessToken() {
		if (!is_file($this->_tokenFile))
			return false;
		return file_get_contents($this->_tokenFile);
	}

	protected function _saveLocalAccessToken($token) {
		file_put_contents($this->_tokenFile, $token);
	}

	protected function _invalLocalAccessToken() {
		@unlink($this->_tokenFile);
	}

	protected function _getAccessTokenByLogin() {
		$my_url = $this->returnUrl;
		$app_id = $this->appId;
		$app_secret = $this->appSerect;
		$email = $this->email;
		$password = $this->password;
		$wc = new WebClient();

		// get login form url (optional)
		$dialog_url = "https://www.facebook.com/dialog/oauth?client_id={$app_id}&redirect_uri={$my_url}";
		$response = $wc->get($dialog_url);
		$this->_writeLog($response, true);
		$form_url = $this->_getLoginFormUrl($response);
		
		// get login form data
		$response = $wc->get($form_url);
		$this->_writeLog($response);
		list($post_url, $lsd, $lgnrnd, $lgnjs, $reg_fb_gate, $reg_fb_ref, $reg_ext_ref, $datr) = $this->_getLoginFormData($response);

		// login
		$cookie = "datr=$datr; reg_fb_gate=$reg_fb_gate; reg_fb_ref=$reg_fb_ref; reg_ext_ref=$reg_ext_ref; fr=0zyktQ7h28ovKnfW5.AWUplvHS6mhXhG_k0A7IhsqxFWg.BSJ-Pc.Zo.FNP.AWX1HVc6; lu=gAMxeP3tM78O1cDuFejuJe_g; locale=en_US";
		$options = array(CURLOPT_COOKIE => $cookie);
		$data = array(
			'lsd' => $lsd,
			'lgnrnd' => $lgnrnd,
			'lgnjs' => $lgnjs,
			'api_key' => $app_id,
			'display' => 'page',
			'enable_profile_selector' => '',
			'legacy_return' => '1',
			'profile_selector_ids' => '',
			'skip_api_login' => '1',
			'signed_next' => '1',
			'trynum' => '1',
			'timezone' => '-420',
			'email' => $email,
			'pass' => $password,
			'default_persistent' => '1',
		);
		$response = $wc->post($post_url, $data, $options);
		$this->_writeLog($response);
		list($s, $sx, $lu, $c_user, $fr) = $this->_getLoggedData($response);
		
		// get user code
		$cookie = "s=$s; xs=$sx; lu=$lu; c_user=$c_user; fr=$fr; datr=$datr";
		$options = array(CURLOPT_COOKIE => $cookie);
		$response = $wc->get($dialog_url, array(), $options);
		$this->_writeLog($response);
		$code = $this->_getCode($response);
		
		// get access token
		$token_url = "https://graph.facebook.com/oauth/access_token?client_id={$app_id}&redirect_uri={$my_url}&client_secret={$app_secret}&code={$code}";
		$response = file_get_contents($token_url);
		$this->_writeLog($response);
		$access_token = $this->_getAccessToken($response);
		
		// save access token
		$this->_saveLocalAccessToken($access_token);
		
		return $access_token;
	}
	
	protected function _writeLog($s, $renew=false) {
		$log_file = Yii::app()->basePath . DIRECTORY_SEPARATOR . 'log.txt';
		if ($renew) @unlink($log_file);
		file_put_contents($log_file, "$s\n\n----\n\n", FILE_APPEND);
	}

	protected function _extractData($regex, $s) {
		if (!preg_match($regex, $s, $matches)) 
			return false;
		return $matches[1];
	}
	
	protected function _getLoginFormUrl($response) {
		return $this->_extractData('/Location: (.*?)\r\n/', $response);
	}
	
	protected function _getLoginFormData($response) {
		$lgnjs = time();
		$post_url = "https://www.facebook.com".$this->_extractData('/action="(.*?)"/', $response);
		$lsd = $this->_extractData('/name="lsd" value="(.*?)"/', $response);
		$lgnrnd = $this->_extractData('/name="lgnrnd" value="(.*?)"/', $response);
		$reg_fb_gate = $this->_extractData('/reg_fb_gate=(.*?);/', $response);
		$reg_fb_ref = $this->_extractData('/reg_fb_ref=(.*?);/', $response);
		$reg_ext_ref = $this->_extractData('/reg_ext_ref=(.*?);/', $response);
		$datr = $this->_extractData('/datr=(.*?);/', $response);
		return array($post_url, $lsd, $lgnrnd, $lgnjs, $reg_fb_gate, $reg_fb_ref, $reg_ext_ref, $datr);
	}
	
	protected function _getLoggedData($response) {
		$s = $this->_extractData('/s=(.*?);/', $response);
		$sx = $this->_extractData('/xs=(.*?);/', $response);
		$lu = $this->_extractData('/lu=(.*?);/', $response);
		$c_user = $this->_extractData('/c_user=(.*?);/', $response);
		$fr = $this->_extractData('/fr=(.*?);/', $response);
		return array($s, $sx, $lu, $c_user, $fr);
	}
	
	protected function _getCode($response) {
		return $this->_extractData('/code=(.*?)#_=_/', $response);
	}

	protected function _getAccessToken($response) {
		return $this->_extractData('/access_token=(.*?)&/', $response);
	}

	public function executeQuery($query, $offset) {
		$access_token = $this->getAccessToken();
		$limit = $this->limit+1;
		$query .= " LIMIT $offset,$limit";
		$this->_writeLog($query);
		$query = urlencode(trim($query));
		$url = "https://graph.facebook.com/fql?access_token={$access_token}&q=$query";
		$response = @file_get_contents($url);

		if ($response===FALSE) {
			$this->_invalLocalAccessToken();
			return array('data'=>array());
		}

		$result = array();
		$response = preg_replace('/("\w+"):(\d+)/', '\\1:"\\2"', $response);
		$data = json_decode($response, true);
		$items = $data['data'];
		
		$result['paging']['offset'] = $offset;
		
		if ($offset>0)
			$result['paging']['previous'] = ($offset > $limit) ? $offset - $limit : 0;

		if (count($items)==$limit) {
			$result['paging']['next'] = $offset + $limit - 1;
			array_pop($items);
		}
		
		$result['items'] = $items;
		return $result;
	}

	/*
	 * Find page by keyword
	 */
	public function findPages($s, $o=0) {
		$q = "SELECT page_id, name, page_url FROM page WHERE CONTAINS('$s') ORDER BY fan_count DESC";
		return $this->executeQuery($q, $o);
	}

	/*
	 * Find group by keyword
	 */
	public function findGroups($s, $o=0) {
		$q = "SELECT gid, name FROM group WHERE CONTAINS('$s')";
		return $this->executeQuery($q, $o);
	}
	
	/*
	 * Find most liked post in group/page. Filter by keyword
	 */
	public function findPosts($s, $p, $o=0) {
		$s = addslashes($s);
		$q = "
			SELECT post_id, message, permalink
			FROM stream 
			WHERE source_id=$p AND strpos(message, '$s')>0
			ORDER BY like_info.like_count DESC
		";
		return $this->executeQuery($q, $o);
	}
	
	/*
	 * Find user who like the post
	 */
	public function findUsersLikePost($post_ids, $o=0) {
		foreach($post_ids as &$id) {
			$id = "'$id'";
		}
		$ids = implode(',', $post_ids);
		
		$q ="
			SELECT uid, profile_url, first_name, middle_name, last_name, email, contact_email, pic_small
			FROM user
			WHERE uid IN (
				SELECT user_id
				FROM like 
				WHERE post_id IN ($ids)
			)
		";
		return $this->executeQuery($q, $o);
	}

}